import { SerializeStream } from "../../Framework/Serialize/SerializeStream";
import { EventEmitter } from "events";
// import { PropertyChangeEvent } from "../../mx/events/PropertyChangeEvent";
type int = number;
//class HandlerId

export enum StreamDispacherDataType {
  Byte,
  Short,
  String,
  Int,
  Size
}

export class StreamDispacher {
  [key: string]: any;
  constructor(
    private keys: {
      key: string;
      type?: StreamDispacherDataType;
    }[]
  ) {
    keys.forEach(({ key }) => {
      Object.defineProperty(this, key, {
        get: () => {
          return this["_" + key];
        },
        set: (val: any) => {
          var old_val = this["_" + key];
          if (old_val !== val) {
            this["_" + key] = val;
            if (this.hasEventListener("propertyChange")) {
              this.propertyChange(key, old_val, val);
            }
          }
        }
      });
    });
  }
  public __write(stream: SerializeStream) {
    this.keys.forEach(({ key, type }) => {
      if (type === undefined) {
        return;
      }
      if (type === StreamDispacherDataType.Byte) {
        stream.writeByte(this[key]);
      } else if (type === StreamDispacherDataType.Short) {
        stream.writeShort(this[key]);
      } else if (type === StreamDispacherDataType.Int) {
        stream.writeInt(this[key]);
      } else if (type === StreamDispacherDataType.String) {
        stream.writeString(this[key]);
      } else if (type === StreamDispacherDataType.Size) {
        stream.writeSize(this[key]);
      }
    });
  }

  public __read(stream: SerializeStream) {
    this.keys.forEach(({ key, type }) => {
      if (type === StreamDispacherDataType.Byte) {
        this[key] = stream.readByte();
      } else if (type === StreamDispacherDataType.Short) {
        this[key] = stream.readShort();
      } else if (type === StreamDispacherDataType.Int) {
        this[key] = stream.readInt();
      } else if (type === StreamDispacherDataType.String) {
        this[key] = stream.readString();
      }
    });
  }

  public addEventListener(
    name: string,
    handler: (...args: any[]) => void,
    useCapture: Boolean = false,
    priority: int = 0,
    useWeakReference: Boolean = false
  ): void {
    this._bindingEventDispatcher.addListener(
      name,
      handler
      // useCapture,
      // priority,
      // useWeakReference
    );
    return;
  }
  public propertyChange(key: string, old_val: any, new_val: any) {
    this.dispatchEvent("propertyChange", key, old_val, new_val);
  }

  public dispatchEvent(name: string, ...args: any[]): Boolean {
    return this._bindingEventDispatcher.emit(name, ...args);
  }

  public hasEventListener(name: string): Boolean {
    return this._bindingEventDispatcher.eventNames().includes(name);
  }

  public removeEventListener(
    name: string,
    handler: (...args: any[]) => void,
    useCapture: Boolean = false
  ): void {
    this._bindingEventDispatcher.removeListener(
      name,
      handler /* , useCapture */
    );
    return;
  }

  public willTrigger(name: string): Boolean {
    // return this._bindingEventDispatcher.willTrigger(name);
    return true;
  }

  private _bindingEventDispatcher: EventEmitter = new EventEmitter();
}
